﻿#include <liveMedia.hh>
#include <BasicUsageEnvironment.hh>
#include <groupsock.hh>
#include <winsock2.h>
#include <ws2tcpip.h>
#include "IngenicVideoSource.h"

UsageEnvironment* env;

class IngenicMediaSubsession : public OnDemandServerMediaSubsession {
public:
    static IngenicMediaSubsession* createNew(UsageEnvironment& env, Boolean reuseFirstSource) {
        return new IngenicMediaSubsession(env, reuseFirstSource);
    }

protected:
    IngenicMediaSubsession(UsageEnvironment& env, Boolean reuseFirstSource)
        : OnDemandServerMediaSubsession(env, reuseFirstSource) {
        env << "IngenicMediaSubsession: Created\n";
    }

    virtual void startStream(unsigned clientSessionId, void* streamToken,
        TaskFunc* rtcpRRHandler, void* rtcpRRHandlerClientData,
        unsigned short& rtpSeqNum, unsigned& rtpTimestamp,
        ServerRequestAlternativeByteHandler* serverRequestAlternativeByteHandler,
        void* serverRequestAlternativeByteHandlerClientData) {

        envir() << "=== INGENIC CLIENT CONNECTED: Session " << clientSessionId << " ===\n";
        OnDemandServerMediaSubsession::startStream(clientSessionId, streamToken,
            rtcpRRHandler, rtcpRRHandlerClientData,
            rtpSeqNum, rtpTimestamp,
            serverRequestAlternativeByteHandler,
            serverRequestAlternativeByteHandlerClientData);
    }

    virtual FramedSource* createNewStreamSource(unsigned clientSessionId, unsigned& estBitrate) {
        envir() << "Creating new Ingenic video stream source for client session: " << clientSessionId << "\n";
        estBitrate = 2000; // 2 Mbps for Ingenic video

        IngenicVideoSource* ingenicSource = IngenicVideoSource::createNew(envir());
        if (ingenicSource == NULL) {
            envir() << "ERROR: Failed to create Ingenic video source\n";
            return NULL;
        }

        // 设置君正视频参数
        ingenicSource->setResolution(1920, 1080);
        ingenicSource->setFramerate(25);
        ingenicSource->setBitrate(2000);

        envir() << "Ingenic video source created successfully\n";

        H264VideoStreamFramer* framer = H264VideoStreamFramer::createNew(envir(), ingenicSource, True);
        if (framer == NULL) {
            envir() << "ERROR: Failed to create H264 video stream framer\n";
            return NULL;
        }

        envir() << "H264 video stream framer created successfully\n";
        return framer;
    }

    virtual RTPSink* createNewRTPSink(Groupsock* rtpGroupsock, unsigned char rtpPayloadTypeIfDynamic, FramedSource* inputSource) {
        envir() << "Creating RTP sink...\n";
        RTPSink* sink = H264VideoRTPSink::createNew(envir(), rtpGroupsock, rtpPayloadTypeIfDynamic);
        if (sink == NULL) {
            envir() << "ERROR: Failed to create RTP sink\n";
        }
        else {
            envir() << "RTP sink created successfully\n";
        }
        return sink;
    }
};

int main(int argc, char** argv) {
    // 初始化Winsock
    WSADATA wsaData;
    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
        return 1;
    }

    // ★★★★ 在创建任何RTSP组件之前设置缓冲区大小 ★★★★
    OutPacketBuffer::maxSize = 100000; // 增加到200KB


    // 初始化任务调度器
    TaskScheduler* scheduler = BasicTaskScheduler::createNew();
    env = BasicUsageEnvironment::createNew(*scheduler);

    *env << "========================================\n";
    *env << "   Ingenic Video Streamer - Live555     \n";
    *env << "========================================\n\n";

    // 创建RTSP服务器
    RTSPServer* rtspServer = RTSPServer::createNew(*env, 8554);
    if (rtspServer == NULL) {
        *env << "ERROR: Failed to create RTSP server on port 8554\n";
        *env << "Reason: " << env->getResultMsg() << "\n";
        *env << "Make sure port 8554 is not in use by another application.\n";
        WSACleanup();
        return 1;
    }
    *env << "RTSP server created successfully on port 8554\n";

    // 创建服务器媒体会话
    ServerMediaSession* sms = ServerMediaSession::createNew(*env, "ingenic",
        NULL,
        "Ingenic Video Stream");

    // 添加君正媒体子会话
    sms->addSubsession(IngenicMediaSubsession::createNew(*env, False));
    rtspServer->addServerMediaSession(sms);

    *env << "Media session 'ingenic' created\n";

    // 输出RTSP URL
    char* url = rtspServer->rtspURL(sms);
    *env << "\n=== STREAM URLS ===\n";
    *env << "Primary: " << url << "\n";
    *env << "Local:   rtsp://localhost:8554/ingenic\n";
    *env << "Loopback: rtsp://127.0.0.1:8554/ingenic\n";
    delete[] url;

    *env << "\n=== STREAM INFORMATION ===\n";
    *env << "Real-time Ingenic video capture encoded via Ingenic SDK (H.264).\n";
    *env << "Low-latency Annex B stream served over RTSP by live555.\n";
    *env << "Resolution: 1920x1080, Framerate: 25fps, Bitrate: 2000kbps\n\n";

    *env << "=== INSTRUCTIONS ===\n";
    *env << "1. Open VLC Media Player\n";
    *env << "2. Go to Media -> Open Network Stream\n";
    *env << "3. Enter: rtsp://localhost:8554/ingenic\n";
    *env << "4. Click Play\n\n";

    *env << "Server is running. Press Ctrl+C to stop.\n";
    *env << "Waiting for client connections...\n\n";

    // 进入主事件循环
    env->taskScheduler().doEventLoop();

    // 清理
    WSACleanup();
    *env << "Server shutdown complete.\n";
    return 0;
}